from . import news_blue
# 导入上下文对象进行在redis中设置session
from flask import session, render_template, current_app, jsonify, request, g
# 导入模型类
from info.models import User, News, Category, Comment, CommentLike
# 导入自定义状态码
from info.utils.response_code import RET
# 导入登录验证装饰器
from info.utils.comments import login_required
# 导入数据库对象
from info import db
from datetime import datetime


# 首页
@news_blue.route('/')
@login_required
def index():
    """
    用户信息的展示
    1.尝试从redis中获取用户id
    2.id存在则查询mysql,将用户信息显示到首页
    :return:
    """
    user = g.user
    # 查询数据库,将新闻模型类查询点击次数,查询结果按照倒序排列
    try:
        news_ob = News.query.filter().order_by(News.clicks.desc()).limit(6)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='排名查询失败')
    # 判断查询结果
    if not news_ob:
        return jsonify(errno=RET.NODATA, errmsg='新闻数据为空')
    # 遍历查询结果,将对象转换成可读字符串
    news_list = []
    for news in news_ob:
       news_list.append(news.to_dict())

    # 新闻分类数据展示
    try:
       categories = Category.query.all()
    except Exception as e:
       current_app.logger.error(e)
       return jsonify(errno=RET.DBERR, errmsg='查询分类数据异常')
    # 判断查询结果
    if not categories:
       return jsonify(errno=RET.NODATA, errmsg='无分类数据')
    # 定义容器存储查询结果
    category_list = []
    # 遍历查询结果
    for category in categories:
       category_list.append(category.to_dict())

    data = {
        'user_info': user.to_dict() if user else None,
        'news_dict_list': news_list,
        'catagory_list': category_list

    }
    return render_template('news/index.html', data=data)


# 前端对应的是index.js
@news_blue.route('/news_list')
def get_news_list():
    """
    首页新闻列表数据
    1、获取参数，cid/page/per_page
    2、检查参数：把参数转成int类型
    3、判断分类id是大于1
    4、根据新闻分类ID查询数据库，按照新闻发布时间进行排序，对排序结果进行分页
    5、获取分页后的新闻数据：总页数、当前页数、数据
    6、返回结果

    :return:
    """
    # 获取参数
    cid = request.args.get("cid", '1')
    page = request.args.get('page', '1')
    per_page = request.args.get("per_page", '10')
    # 检查参数，需要把参数转成int－－－－－－－－－－－－>不是必须传入的,不用检查参数完整性
    try:
        cid, page, per_page = int(cid), int(page), int(per_page)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数的格式错误')
    # 定义过滤条件,filter为空：则选中所有的,没有分类
    filters = []
    # 判断分类id是否是最新
    if cid > 1:
        filters.append(News.category_id == cid)
    # 根据分类id查询数据库
    try:
        # 对过滤查询执行排序，对排序结果进行分页(拆包*filters＝News.category_id == cid)
        paginate = News.query.filter(*filters).order_by(News.create_time.desc()).paginate(page, per_page, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询新闻列表数据异常')
    # 获取分页后的新闻数据,总页数，当前页数
    news_list = paginate.items
    total_page = paginate.pages
    current_page = paginate.page
    # 定义列表
    news_dict_list = []
    # 遍历分页后的新闻数据
    for news in news_list:
        news_dict_list.append(news.to_dict())
    # 定义data字典
    data = {
        'news_dict_list': news_dict_list,
        'total_page': total_page,
        'current_page': current_page
    }
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='OK', data=data)


@news_blue.route('/<int:news_id>')
@login_required
def get_news_detail(news_id):
    """
    新闻详情页面
    1、尝试获取用户信息
    2、根据news_id查询mysql
    3、判断查询结果是否存在
    4、进入新闻详情页面，需要让新闻的clicks加1，提交数据
    5、构造字典直接返回数据

    :param news_id:
    :return:
    """
    user = g.user
    # 根据news_id查询数据库
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询新闻详情数据失败')
    # 判断查询结果是否存在
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='无新闻详情数据')
    # 让新闻的点击次数加1
    news.clicks += 1
    # 提交数据到mysql数据库
    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 新闻点点击排行
    try:
        # News.qeury.order_by(News.clicks.desc()).limit(6)
        news_list = News.query.filter().order_by(News.clicks.desc()).limit(6)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询新闻数据异常')
    # 判断查询结果是否存在
    if not news_list:
        return jsonify(errno=RET.NODATA, errmsg='无新闻数据')
    # 定义容器列表用来存储遍历后的数据
    news_dict_list = []
    # 遍历查询结果，把查询到的对象转成可读字符串
    for index in news_list:
        news_dict_list.append(index.to_dict())

    # 查询用户信息
    try:
        user = User.query.get(user.id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据异常')
    # 判断查询结果新闻是否存在
    if not user:
        return jsonify(errno=RET.NODATA, errmsg='用户不存在')
    # 查询评论信息
    try:
        comment = Comment.query.filter_by(news_id=news_id, parent_id=None).order_by(Comment.create_time.desc()).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据异常')
    comment_list = []
    comment_son_list = []
    # 判断查询结果评论是否存在
    if not comment:
        comment_list = []
    count = 0
    for com in comment:
        comment_list.append(com.to_dict())
        print('父评论id', com.id)
        try:
            comment_son = Comment.query.filter_by(parent_id=com.id).order_by(Comment.create_time.desc()).all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询数据异常')
        if not comment_son:
            comment_son_list.append('')
        for com in comment_son:
            comment_son_list.append(com.to_dict())
        count += 1
    print('所有父评论', comment_list)
    print('所有子评论', comment_son_list)
    print('个数', count)
    # 构造字典
    data = {
        'comment_list': comment_list,
        'comment_son_list': comment_son_list,
        'user_info': user.to_dict() if user else None,
        'news_detail': news.to_dict(),
        'news_dict_list': news_dict_list,
        'count': count
    }

    # 加载模板渲染数据
    return render_template('news/detail.html', data=data)


@news_blue.route('/news_collect', methods=['POST'])
@login_required
def news_collect():
    """
    收藏和取消收藏
    1、尝试获取用户的信息
    2、如果未登录直接终止程序的执行
    3、获取参数，post请求的json数据，action和news_id
    4、检查参数，判断参数的完整性
    5、把news_id转成int类型
    6、判断action参数必须为collect或者cancel_collect；
    必须为收藏或取消收藏
    7、根据news_id查询数据库，
    8、判断查询结果是否存在
    9、判断用户选择的是收藏还是取消收藏
    10、返回结果
    :return:
    """
    # 尝试获取用户信息
    user = g.user
    # 判断用户信息是否存在
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    # 获取post请求的参数
    news_id = request.json.get('news_id')
    action = request.json.get('action')
    # 判断参数的完整性
    if not all([news_id, action]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')
    # 检查news_id参数的格式
    try:
        news_id = int(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg='参数的格式错误')
    # 检查action参数
    if action not in ['collect', 'cancel_collect']:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')
    # 根据news_id查询mysql数据库
    try:
        news = News.query.get(news_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询数据异常')
    # 判断查询结果新闻是否存在
    if not news:
        return jsonify(errno=RET.NODATA, errmsg='新闻数据不存在')
    # 判断用户action选择的是收藏还是取消收藏
    if action == 'collect':
        # 判断用户之前未收藏过该新闻
        if news not in user.collection_news:
            user.collection_news.append(news)
    else:
        user.collection_news.remove(news)

    # 提交数据到数据库中
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据异常')
    # 返回结果
    return jsonify(errno=RET.OK, errmsg='OK')


# 新闻评论
@news_blue.route('/news_comment', methods=['POST'])
@login_required
def news_comment():
    """
    获取前端的参数
    :return:
    """
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    comment_sub = request.json.get('comment_sub')
    news_id = request.json.get('news_id')
    user_id = user.id
    if not all([comment_sub, news_id, user_id]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')
    # 保存评论内容到mysql数据库中
    comment = Comment()
    comment.user_id = user.id
    comment.news_id = news_id
    comment.content = comment_sub
    comment.create_time = datetime.now()
    # 提交数据
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    return jsonify(errno=RET.OK, errmsg='OK')


# 新闻子评论
@news_blue.route('/news_son_comment', methods=['POST'])
@login_required
def news_son_comment():
    """
    获取前端的参数
    :return:
    """
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    comment_sub = request.json.get('comment_sub')
    news_id = request.json.get('news_id')
    comment_id = request.json.get('comment_id')
    user_id = user.id
    if not all([comment_sub, news_id, user_id, comment_id]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')
    # 保存评论内容到mysql数据库中
    comment = Comment()
    comment.user_id = user.id
    comment.news_id = news_id
    comment.content = comment_sub
    comment.parent_id = comment_id
    comment.create_time = datetime.now()
    # 提交数据
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # try:
    #     comment_son = Comment.query.filter_by(parent_id=comment_id).all()
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.DBERR, errmsg='数据库错误')
    # if not comment_son:
    #     return jsonify(errno=RET.NODATA, errmsg='无数据')
    # comment_son_list = []
    # for comment in comment_son:
    #     comment_son_list.append(comment.to_dict())
    # data_son = {
    #     "comment_son_list": comment_son_list
    # }
    return jsonify(errno=RET.OK, errmsg='OK')


@news_blue.route('/comment_like', methods=['POST'])
@login_required
def comment_like():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='用户未登录')
    comment_id = request.json.get('comment_id')
    print(comment_id, type(comment_id))
    user_id = user.id
    if not all([comment_id, user_id]):
        return jsonify(errno=RET.DATAERR, errmsg='参数不完整')
    # 先查一查该用户是否点赞过该评论
    try:
        userlike_id = CommentLike.query.filter_by(comment_id=comment_id).all()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库出错')
    if userlike_id:
        for like_user in userlike_id:
            if like_user.user_id == user.id:
                # 保存评论点击数到mysql数据库中
                try:
                    comment = Comment.query.filter_by(id=comment_id).first()
                except Exception as e:
                    current_app.logger.error(e)
                    return jsonify(errno=RET.DBERR, errmsg='数据库出错')
                if not comment:
                    return jsonify(errno=RET.NODATA, errmsg='无数据')
                if comment.like_count <= 0:
                    comment.like_count = 0
                else:
                    comment.like_count -= 1
                comment.update_time = datetime.now()
                # 提交数据
                try:
                    db.session.add(comment)
                    db.session.commit()
                except Exception as e:
                    current_app.logger.error(e)
                    db.session.rollback()
                    return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
                # 删除评论点赞对用的用户
                try:
                    userlike_user = CommentLike.query.filter_by(user_id=user_id).first()
                except Exception as e:
                    current_app.logger.error(e)
                    return jsonify(errno=RET.DBERR, errmsg='数据库出错')
                if not userlike_user:
                    return jsonify(errno=RET.NODATA, errmsg='数据缺失')
                # 提交数据
                try:
                    db.session.delete(userlike_user)
                    db.session.commit()
                except Exception as e:
                    current_app.logger.error(e)
                    db.session.rollback()
                    return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
                return jsonify(errno=RET.DATAEXIST, errmsg='您已经取消点赞')
    # 保存评论点击数到mysql数据库中
    try:
        comment = Comment.query.filter_by(id=comment_id).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库出错')
    if not comment:
        return jsonify(errno=RET.NODATA, errmsg='无数据')
    comment.like_count += 1
    comment.update_time = datetime.now()
    # 提交数据
    try:
        db.session.add(comment)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    # 保存数据到点赞表
    comment_love = CommentLike()
    comment_love.create_time = datetime.now()
    comment_love.comment_id = comment_id
    comment_love.user_id = user_id
    # 提交数据
    try:
        db.session.add(comment_love)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='保存数据失败')
    try:
        comment_l = Comment.query.filter_by(id=comment_id).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库出错')
    if not comment_like:
        return jsonify(errno=RET.NODATA, errmsg='无数据')

    data = {
        'count': comment_l.to_dict()
    }
    return jsonify(errno=RET.OK, errmsg='OK', data=data)


# 图标logo
@news_blue.route('/favicon.ico')
def favicon():
    # 调用current_app的发送静态文件方法发送静态文件给浏览器
    return current_app.send_static_file('news/favicon.ico')